package com.orangelife.session.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
import net.sf.ehcache.ObjectExistsException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.orangelife.session.Session;
import com.orangelife.session.SessionIdGenerator;
import com.orangelife.session.SessionManager;





@Service("sessionManager")
public class SimpleSessionManager implements SessionManager {

	private Logger logger = LoggerFactory.getLogger(SimpleSessionManager.class);

	private static final String CACHE_KEYOF_SESSIONIDS = "CACHE_KEYOF_SESSIONIDS";

	//@Resource(name = "cacheManager")
	private CacheManager cacheManager;

	@Resource(name = "sessionIdGenerator")
	private SessionIdGenerator sessionIdGenerator;

	//@PostConstruct
	public void init() {
		;
		try {
			cacheManager.addCache(CACHE_KEYOF_SESSIONIDS);
		} catch (ObjectExistsException e) {
			logger.info("duplicate cache defined!" + CACHE_KEYOF_SESSIONIDS);
		}

	}

	@SuppressWarnings("unchecked")
	@Override
	public List<String> ids() {

		Cache idsCache = cacheManager.getCache(CACHE_KEYOF_SESSIONIDS);
		return (List<String>) idsCache.getKeysWithExpiryCheck();
	}

	@Override
	public Session create() {
		String sessionId = sessionIdGenerator.getId();
		Session session = new SimpleSession(sessionId);

		publish(session);
		return session;
	}

	@Override
	public void remove(String id) {
		Cache idsCache = cacheManager.getCache(CACHE_KEYOF_SESSIONIDS);
		idsCache.remove(id);
	}

	@Override
	public Session getSession(String id) {
		Cache idsCache = cacheManager.getCache(CACHE_KEYOF_SESSIONIDS);
		Element e = idsCache.get(id);
		if (e == null)
			return null;

		return (Session) e.getValue();
	}

	void publish(Session session) {
		Cache idsCache = cacheManager.getCache(CACHE_KEYOF_SESSIONIDS);
		idsCache.put(new Element(session.getId(), session));
	}

	public long getCreationTime(String id) {
		Cache idsCache = cacheManager.getCache(CACHE_KEYOF_SESSIONIDS);
		Element e = idsCache.get(id);
		if (e == null)
			return -1;

		return e.getCreationTime();
	}

	public long getLastAccessedTime(String id) {
		Cache idsCache = cacheManager.getCache(CACHE_KEYOF_SESSIONIDS);
		Element e = idsCache.get(id);
		if (e == null)
			return -1;

		return e.getLastAccessTime();
	}

	private class SimpleSession implements Session {

		/**
		 * 
		 */
		private static final long serialVersionUID = -3572613781331351752L;
		private String id;
		private Map<String, Object> values = new HashMap<String, Object>();

		/**
		 * 反序列化时使用该接口
		 */
		@SuppressWarnings("unused")
		SimpleSession() {
		}

		SimpleSession(String id) {
			this.id = id;
		}

		@Override
		public String getId() {
			return id;
		}

		@Override
		public long getCreationTime() {
			return SimpleSessionManager.this.getCreationTime(id);
		}

		@Override
		public long getLastAccessedTime() {
			return SimpleSessionManager.this.getLastAccessedTime(id);
		}

		@Override
		public void invalidate() {
			SimpleSessionManager.this.remove(id);
		}

		@Override
		public void setAttibute(String key, Object value) {
			SimpleSession session = (SimpleSession) SimpleSessionManager.this
					.getSession(id);
			session.values.put(key, value);
			SimpleSessionManager.this.publish(session);
		}

		@Override
		public Object getAttribute(String key) {
			SimpleSession session = (SimpleSession) SimpleSessionManager.this
					.getSession(id);
			return session.values.get(key);
		}

		@Override
		public Set<String> getAttributeKeys() {
			SimpleSession session = (SimpleSession) SimpleSessionManager.this
					.getSession(id);
			return session.values.keySet();
		}
	}

}
